import React, { useRef, useState } from "react";
import styles from "./index.module.scss";
import interact from "interactjs";
import { DrawerForm, ProFormDependency, ProFormItem, ProFormSelect, ProFormTimePicker, ProFormUploadDragger } from "@ant-design/pro-components";
import { Button, Image as AntImage, Modal, Statistic } from "antd";
import { SettingOutlined } from "@ant-design/icons";
import dayjs from "dayjs";

export const Game = () => {
    const [imagePath, setImagePath] = useState<string>("https://img0.baidu.com/it/u=2997055567,379692641&fm=253&fmt=auto&app=138&f=GIF?w=338&h=333");
    const [widthBlock, setWidthBlock] = useState<number>(3);
    const [heightBlock, setHeightBlock] = useState<number>(3);
    const [level, setLevel] = useState<number>(3);

    const [time, setTime] = useState<string>("00:30:00");
    const candidateDivRef = useRef<HTMLDivElement>(null);
    const jigsawGameDivRef = useRef<HTMLDivElement>(null);

    const result = React.useMemo(() => new Array(widthBlock * heightBlock).fill(false), [widthBlock, heightBlock]);

    const onBuild = React.useCallback(async () => {
        const image = new Image();
        image.src = imagePath;
        await new Promise(resolve => {
            image.onload = () => {
                resolve(null);
            };
        });
        const candidateDivChildren: HTMLCanvasElement[] = [];
        const jigsawGameDivChildren: HTMLDivElement[] = [];
        const image_width = image.width;
        const image_height = image.height;
        for (let i = 0; i < widthBlock; i++) {
            for (let j = 0; j < heightBlock; j++) {
                const canvas = document.createElement("canvas") as HTMLCanvasElement;
                const blockWidth = ( jigsawGameDivRef.current?.clientWidth || 0 ) / widthBlock;
                const blockHeight = ( jigsawGameDivRef.current?.clientHeight || 0 ) / widthBlock;
                canvas.width = blockWidth;
                canvas.height = blockHeight;
                const context = canvas.getContext("2d");
                context?.drawImage(image, i * image_width / widthBlock, j * image_height / heightBlock, image_width / widthBlock, image_height / heightBlock, 0, 0, blockWidth, blockHeight);
                canvas.dataset.i = String(j);
                canvas.dataset.j = String(i);
                candidateDivRef.current?.appendChild(canvas);
                candidateDivChildren.push(canvas);
                interact(canvas).draggable({
                    autoScroll: false,
                    listeners: {
                        move: function(event) {
                            const target = event.target as HTMLElement;
                            target.style.zIndex = "9999";
                            if (event.dropzone?.target) {
                                const threshold = Math.max(blockWidth, blockHeight) / 2;
                                if (Math.abs(event.dx) < threshold || Math.abs(event.dy) < threshold) {
                                    return;
                                }
                            }
                            const dataX = target.getAttribute("data-x") || "0";
                            const dataY = target.getAttribute("data-y") || "0";
                            const x = parseFloat(dataX) + event.dx;
                            const y = parseFloat(dataY) + event.dy;
                            target.style.transform = "translate(" + x + "px, " + y + "px)";
                            target.setAttribute("data-x", x);
                            target.setAttribute("data-y", y);
                        },
                        end(event) {
                            const canvas = event.target as HTMLElement;
                            const div = event.relatedTarget as HTMLElement;
                            if (div != null) {
                                const i_canvas = parseInt(canvas.dataset.i as string);
                                const i_div = parseInt(div.dataset.i as string);
                                const j_canvas = parseInt(canvas.dataset.j as string);
                                const j_div = parseInt(div.dataset.j as string);
                                const index = i_canvas * heightBlock + j_canvas;
                                if (i_canvas === i_div && j_canvas === j_div) {
                                    const index = i_canvas * heightBlock + j_canvas;
                                    result[index] = true;
                                    console.log(result);
                                    if (!result.includes(false)) {
                                        Modal.success({
                                            content: "游戏成功"
                                        });
                                    }
                                } else {
                                    result[index] = false;
                                }
                            }
                            canvas.style.zIndex = "10";
                        }
                    }
                });
                const div = document.createElement("div");
                div.style.width = blockWidth + "px";
                div.style.height = blockHeight + "px";
                div.dataset.i = String(i);
                div.dataset.j = String(j);
                interact(div).dropzone({
                    accept: "canvas",
                    ondragenter: function(event) {
                        const div = event.target as HTMLElement;
                        const canvas = event.relatedTarget as HTMLElement;
                        const divX = div.getBoundingClientRect().left;
                        const divY = div.getBoundingClientRect().top;
                        const canvasX = canvas.getBoundingClientRect().left;
                        const canvasY = canvas.getBoundingClientRect().top;
                        const dataX = canvas.getAttribute("data-x") || "0";
                        const dataY = canvas.getAttribute("data-y") || "0";
                        const x = divX - canvasX + parseFloat(dataX);
                        const y = divY - canvasY + parseFloat(dataY);
                        canvas.style.transform = "translate(" + x + "px, " + y + "px)";
                        canvas.setAttribute("data-x", String(x));
                        canvas.setAttribute("data-y", String(y));
                    }
                });
                jigsawGameDivRef.current?.appendChild(div);
                jigsawGameDivChildren.push(div);
            }
        }
        return () => {
            jigsawGameDivChildren.forEach(res => {
                jigsawGameDivRef.current?.removeChild(res);
            });
            candidateDivChildren.forEach(res => {
                candidateDivRef.current?.removeChild(res);
            });
        };
    }, [heightBlock, imagePath, widthBlock, time]);


    React.useEffect(() => {
        const f = onBuild();
        const startTime = Date.now();
        const interval = setInterval(() => {
            const minute = dayjs(Date.now()).diff(dayjs(startTime), "minute");
            const ready = dayjs(time, "HH:mm:ss").diff(dayjs("00:00:00", "HH:mm:ss"), "minute");
            if (minute >= ready) {
                Modal.warning({
                    content: "游戏结束"
                });
                clearInterval(interval);
            }
        }, 1000);
        return () => {
            f.then(res => res());
            clearInterval(interval);
        };
    }, [onBuild, time]);

    return (
        <div className={styles.container}>
            <div className={styles.block_2} ref={jigsawGameDivRef}></div>
            <div ref={candidateDivRef} className={styles.block_1}>
            </div>
            <Statistic.Countdown className={styles.block_3} title="剩余时间"
                                 value={dayjs(time, "HH:mm:ss").diff(dayjs("00:00:00", "HH:mm:ss"), "minute").valueOf() * 60 * 1000 + Date.now()} />
            <DrawerForm
                title="游戏配置"
                trigger={
                    <Button type="ghost" className={styles.button_1}>
                        <SettingOutlined size={80} />
                        游戏设置
                    </Button>
                }
                drawerProps={{
                    destroyOnClose: true
                }}
                onFinish={async (formData) => {
                    setWidthBlock(formData.level);
                    setHeightBlock(formData.level);
                    setLevel(formData.level);
                    setTime(formData.time);
                    if (formData.image) {
                        const image: string = await new Promise((resolve) => {
                            const reader = new FileReader();
                            reader.readAsDataURL(formData.image[0].originFileObj as Blob);
                            reader.onload = () => resolve(reader.result as string);
                        });
                        setImagePath(image);
                    }
                    return true;
                }}
            >
                <ProFormSelect
                    options={[{ value: 5, label: "高难度" }, { value: 4, label: "中难度" }, { value: 3, label: "低难度" }]}
                    name="level"
                    initialValue={level}
                    label="游戏难度"
                />
                <ProFormTimePicker style={{ width: "100%" }} name="time" label="时间设定" initialValue={time} />
                <ProFormUploadDragger fieldProps={{ beforeUpload: () => false }} max={1} action="" label="拼图图像设定" name="image" />
                <ProFormDependency name={["image"]}>
                    {
                        ({ image }) => {
                            return <ProFormItem label="图像预览">
                                <AntImage src={imagePath} />
                            </ProFormItem>;
                        }
                    }
                </ProFormDependency>
            </DrawerForm>
        </div>
    );
};

